package com.angcyo.javafx.ui

import javafx.scene.image.Image
import javafx.scene.image.PixelFormat
import javafx.scene.image.WritableImage
import java.awt.image.BufferedImage
import java.io.*
import java.nio.file.Files
import java.nio.file.Paths
import java.util.*
import javax.imageio.ImageIO


/**
 * Email:angcyo@126.com
 * @author angcyo
 * @date 2021/01/05
 */

/**从[Image]中, 获取指定矩形位置的[Image]*/
fun Image.clipRect(x: Int, y: Int, width: Int, height: Int): WritableImage =
    WritableImage(pixelReader, x, y, width, height)

/**
 * https://stackoverflow.com/questions/38095984/convert-javafx-image-object-to-byte-array
 * */
fun Image.toByteArray(): ByteArray {
    val width = width.toInt()
    val height = height.toInt()

    val pixelBytes = ByteArray(width * height * 4)
    //println(pixelBytes.size) // 367928 bytes

    pixelReader.getPixels(
        0, 0, width, height,
        PixelFormat.getByteBgraInstance(),
        pixelBytes, 0, width * 4
    )

    return pixelBytes
}

/**保存到文件*/
fun Image.saveToFile(file: File, formatName: String = "png"): Boolean {
    return ImageIO.write(UIClientImpl.toBufferedImage(this), formatName, file)
}

fun BufferedImage.saveToFile(file: File, formatName: String = "png"): Boolean {
    return ImageIO.write(this, formatName, file)
}

/**https://mkyong.com/java/how-to-convert-bufferedimage-to-byte-in-java*/
fun Image.toBufferedImage(): BufferedImage? = UIClientImpl.toBufferedImage(this)

@Throws(IOException::class)
fun BufferedImage.toByteArray(format: String = "png"): ByteArray {
    val output = ByteArrayOutputStream()
    ImageIO.write(this, format, output)
    return output.toByteArray()
}

@Throws(IOException::class)
fun ByteArray.toBufferedImage(): BufferedImage? {
    val input: InputStream = ByteArrayInputStream(this)
    return ImageIO.read(input)
}

/**
 * https://stackoverflow.com/questions/38095984/convert-javafx-image-object-to-byte-array
 * */
fun ByteArray.toImage(width: Int, height: Int): WritableImage {
    val image = WritableImage(width, height)
    image.pixelWriter.setPixels(
        0, 0, width, height,
        PixelFormat.getByteBgraInstance(),
        this, 0, width * 4
    )
    return image
}

fun File.toByteArray(): ByteArray? {
    return Files.readAllBytes(Paths.get(absolutePath))
}

/**https://stackoverflow.com/questions/49011802/converting-javafx-image-to-from-base64*/
fun ByteArray.toImage(): Image {
    val inputStream = Base64.getDecoder().wrap(ByteArrayInputStream(this))
    return Image(inputStream)
}

/**将[ByteArray]转换成[Base64]字符串*/
fun ByteArray.toBase64(): String = Base64.getEncoder().encodeToString(this)

fun File.toImage() = Image("file:$absolutePath")

fun String.base64Encode(): String = Base64.getEncoder().encodeToString(toByteArray(Charsets.UTF_8))

fun String.base64Decoder(): String = Base64.getDecoder().decode(toByteArray(Charsets.UTF_8)).toString(Charsets.UTF_8)